#include "Meteoroids.h"
#include "..\..\GameEventData.h"
#include "..\..\AstroMath.h"
#include "..\..\Constants.h"

Meteoroids::~Meteoroids(void) {
	clear();
}

void Meteoroids::clear() {
	MeteoroidIterator it = m_Meteoroids.begin();
	while ( it != m_Meteoroids.end() ) {
		delete it->sprite;
		m_CD.remove(it->handle);
		it = m_Meteoroids.erase(it);			
	}	
	TrailParts::iterator tpi = m_TrailParts.begin();
	while ( tpi != m_TrailParts.end() ) {
		delete tpi->sprite;
		tpi = m_TrailParts.erase(tpi);
	}	
}
// ----------------------------------------------------------
// Init method
// ----------------------------------------------------------
void Meteoroids::init() {
	//m_Sprites = new ds::DynamicSpriteNode("Meteoroids","TexturesMaterial",ds::SCM_MODULATE);
	//gEngine->getWorld().attachNode(m_Sprites,"Base");	
}

// ----------------------------------------------------------
//
// ----------------------------------------------------------
void Meteoroids::createBouncing() {
	gEngine->getAudioManager().play("Warning",50,false);
	float step = SCR_MAX_X / m_SpawnCount;
	float start = 10.0f;
	for ( int i = 0 ; i < m_SpawnCount; ++i ) {
		Meteoroid m;
		m.startPos = createPosition(0,start,step);
		m.midPos = m.startPos;
		m.endPos = createPosition(2,start,step);
		if ( m.endPos.x > m.startPos.x ) {
			m.midPos.x = m.endPos.x;
		}
		if ( m.endPos.y < m.startPos.y ) {
			m.midPos.y = m.endPos.y;
		}
		m.sprite = new ds::Sprite(m.startPos,ds::Rect(125,0,60,60));
		m.handle = m_CD.addCircle(m.startPos,ds::Vec2(30,30),30.0f,METEOROID_ID);
		m.timer = 0.0f;
		m.side = 0;
		m.energy = METEOROID_ENERGY;
		m.lastSpawn = ds::Vec2(0,0);
		m_Meteoroids.push_back(m);
		start += step;
	}
}

void Meteoroids::hit(ds::CDHandle handle) {
	MeteoroidIterator it = m_Meteoroids.begin();
	while ( it != m_Meteoroids.end() ) {
		if ( it->handle == handle ) {
			it->energy -= 10;
			if ( it->energy <= 0 ) {
				// remove it
				delete it->sprite;
				m_CD.remove(it->handle);
				it = m_Meteoroids.erase(it);
				TrailParts::iterator tpi = m_TrailParts.begin();
				while ( tpi != m_TrailParts.end() ) {
					if ( tpi->handle == handle ) {
						delete tpi->sprite;
						tpi = m_TrailParts.erase(tpi);
					}
					else {					
						++tpi;
					}
				}
			}
			else {
				++it;
			}
		}
		else {
			++it;
		}
	}
}
// ----------------------------------------------------------
//
// ----------------------------------------------------------
void Meteoroids::update(float elapsed) {
	m_SpawnTimer += elapsed;
	if ( m_SpawnTimer > 10.0f ) {
		createBouncing();
		m_SpawnTimer = 0.0f;
	}
	// move meteoroids
	MeteoroidIterator it = m_Meteoroids.begin();
	while ( it != m_Meteoroids.end() ) {
		it->timer += elapsed * 0.35f;
		if ( it->timer > 1.0f ) {
			delete it->sprite;
			m_CD.remove(it->handle);
			it = m_Meteoroids.erase(it);			
		}
		else {
			it->sprite->position = spline(*it);
			it->sprite->rotation = it->timer * TWO_PI;
			float dist = it->sprite->position.distance(it->lastSpawn);
			m_CD.setPosition(it->handle,it->sprite->position);
			if ( dist > 40.0f ) {
				it->lastSpawn = it->sprite->position;
				TrailPart tp;
				tp.sprite = new ds::Sprite(it->sprite->position,ds::Rect(350,250,60,60),ds::Color(0.3f,0.3f,0.3f,1.0f),1.0f,1.0f,0.0f);
				tp.sprite->rotation = it->sprite->rotation;
				tp.timer = 0.0f;
				tp.handle = it->handle;
				m_TrailParts.push_back(tp);
			}
			++it;
		}		
	}
	TrailParts::iterator tpi = m_TrailParts.begin();
	while ( tpi != m_TrailParts.end() ) {
		tpi->timer += elapsed;
		if ( tpi->timer > 2.0f ) {
			delete tpi->sprite;
			tpi = m_TrailParts.erase(tpi);
		}
		else {
			ds::Color c = tpi->sprite->color;
			c.a = 0.5f - tpi->timer * 1.0f;
			clamp(&c.a,0.0f,1.0f);
			tpi->sprite->color = c;
			++tpi;
		}
	}
	for ( size_t i = 0; i < m_TrailParts.size(); ++i ) {
		m_Sprites->addSprite(m_TrailParts[i].sprite);
	}
	// add all meteoroids
	for ( size_t i = 0; i < m_Meteoroids.size();++i ) {
		m_Sprites->addSprite(m_Meteoroids[i].sprite);
	}	
}

// ----------------------------------------------------------
//
// ----------------------------------------------------------
ds::Vec2 Meteoroids::createPosition(int side,float min,float max) {
	float right = SCR_MAX_X+30.0f;
	float bottom = SCR_MAX_Y + 30.0f;
	float rx = min + rand() * max;
	float ry = 60.0f + rand() * bottom;
	switch ( side ) {
		case 0 : return ds::Vec2(rx,-30.0f);
		case 1 : return ds::Vec2(right,ry);
		case 2 : return ds::Vec2(rx,bottom);
		case 3 : return ds::Vec2(-30.0f,ry);
	}
	return ds::Vec2(rx,60.0f);
}
// ----------------------------------------------------------
//
// ----------------------------------------------------------
ds::Vec2 Meteoroids::spline(Meteoroid& meteoroid) {
	float t = meteoroid.timer;
	float dx = (1.0f - t) * ( 1.0f - t) * meteoroid.startPos.x;
	dx += 2.0f * t * ( 1.0f - t) * meteoroid.midPos.x;
	dx += t * t * meteoroid.endPos.x;
	float dy = (1.0f - t) * ( 1.0f - t) * meteoroid.startPos.y;
	dy += 2.0f * t * ( 1.0f - t) * meteoroid.midPos.y;
	dy += t * t * meteoroid.endPos.y;
	return ds::Vec2(dx,dy);
}
